'''
Created on 26.12.2013

@author: i.jentson
'''
class ExpressionParser:
    # Input syntax
        # exp :- restr [op exp] | '(' exp ')' .
        # restr :- ('+'|'-') prop .
        # op :- '|' | '&' .
        # prop :- ID .
    # Output syntax
        # res :- << {'op':op, 'args':sr} >>.
        # op :- 'and' | 'or' . 
        # sr :- << [{'value':value, 'type':type}] >>.
        # value :- '+' | '-' .
        # type :- 'exp' | ID .
        
    m_exp = ''
    m_buf = ''
    m_idx = -1
    m_chr = ''
    m_sym = ''
    m_val = ''
    m_res = {'op':'', 'args':[]}
    m_err = []
    
    def __init__(self, p_exp):
        self.m_exp = p_exp
        self.reset()
        
    def reset(self):
        self.m_buf = self.m_exp
        self.m_idx = -1
        self.m_res = {'op':'', 'args':[]}
    
    def getChr(self):
        l_len = len(self.m_buf)
        self.m_chr = ''
        self.m_idx += 1
        if self.m_idx < l_len:
            while self.m_buf[self.m_idx].isspace():
                if self.m_idx+1 < l_len: self.m_idx += 1
                else: break
            if self.m_idx < l_len:     
                self.m_chr = self.m_buf[self.m_idx]
        
    def getSym(self):
        self.m_sym = ''
        self.m_val = ''
        self.getChr()
        if self.m_chr != '':
            if self.m_chr in ('+','-','|','&','(',')'):
                self.m_val = self.m_chr
                self.m_sym = 'OP'
            elif self.m_chr.isalpha():
                self.m_val = self.m_chr
                self.getChr()
                while self.m_chr != '' and self.m_chr.isalpha():
                    self.m_val = self.m_val + self.m_chr
                    self.getChr()
                self.m_idx -= 1
                self.m_sym = 'ID'
            else:
                self.m_val = self.m_chr
                self.m_sym = 'ERR'
        
    def getExp(self):
        l_args = []
        l_op = ''
        if self.m_sym == '': self.getSym()
        while self.m_sym != '':
            if self.m_sym == 'OP':
                if self.m_val == '(':
                    self.getSym()
                    l_exp = self.getExp()
                    if self.m_sym == 'OP' and self.m_val == ')':
                        l_args.append({'type':'exp', 'value':l_exp})
                    elif self.m_sym == '': break
                elif self.m_val == ')':
                    break
                elif self.m_val == '&':
                    if l_op == '': l_op ='and'
                    elif l_op == 'and': pass
                    else: self.m_err.append('Unexpected symbol '+self.m_val + ' on position ' + str(self.m_idx+1))
                elif self.m_val == '|':
                    if l_op == '': l_op ='or'
                    elif l_op == 'or': pass
                    else: self.m_err.append('Unexpected symbol '+self.m_val + ' on position ' + str(self.m_idx+1))
                elif self.m_val in ('+','-'):
                    l_val = self.m_val
                    self.getSym()
                    if self.m_sym == 'ID':
                        l_args.append({'type':self.m_val, 'value':l_val})
                    else: self.m_err.append('Unexpected symbol '+self.m_val + ' on position ' + str(self.m_idx+1))
            else: self.m_err.append('Unexpected symbol '+self.m_val + ' on position ' + str(self.m_idx+1))
            self.getSym()
        if l_op == '' and len(l_args) > 0: l_op = 'and'
        return {'op':l_op, 'args':l_args}
    
    def json(self):
        self.reset()
        self.m_res = self.getExp()
        if len(self.m_err) > 0: l_res = []
        else: l_res = [self.m_res]
        return l_res
                        
                
                
                    